﻿/// <reference path="../App.js" />

(function () {
    "use strict";
    var exampleTable;
    // The initialize function must be run each time a new page is loaded
    Office.initialize = function (reason) {
        $(document).ready(function () {
            app.initialize();
            
            //Why not load example task data when page initialize? 
            //It may clear up existing data
            $('#insertExampleData').click(insertExampleData);
            $('#getData').click(getData);
            document.getElementById('message').style.color = 'black';
        });
    };    

    //Delete table rows
    function cleanTablerow(tableName) {
        while (document.getElementById(tableName).rows.length > 0) {
            document.getElementById(tableName).deleteRow(0);
        }
    }

    function createSimplyTable(taskData) {
        cleanTablerow("dataTable");
        taskData = categoryTaskByDate(taskData);
        var table = document.getElementById("dataTable");   
        var rowCount = taskData.task.length;
        var cellWidth;
        //Risk: may meet different date format for different regions
        var dateIndex = taskData.dateMin;
        var dateShort;
        var dateSpan = taskData.dateSpan;
        var headDates = new Array();
        var taskTag = 0;
        var isConflict = false;
        for (var i = 0; i < rowCount + 1; i++) {
            var row = table.insertRow(i);
            for (var j = 0; j < dateSpan + 1; j++) {
                var cell = row.insertCell(j);
                cell.id = i.toString() + j.toString();
                cell.style.width = "30px";
                //initialize the first row as table head
                if (i == 0) {
                    dateShort = dateIndex.getMonth() + 1 + "/" + dateIndex.getDate();
                    cell.innerHTML = dateShort;
                    //Hidden two days by using the same color as background
                    //Why need interval? Since the space limit, will have trancation if show all days
                    if (j % 2 != 0) {
                        cell.style.color = "#EEEEEE";
                    }
                    headDates[j] = dateIndex.toDateString();
                    dateIndex.setDate(dateIndex.getDate() + 1);
                    if (taskData.dailyResource[headDates[j]] > parseFloat(document.getElementById('message').value)) {
                        cell.style.background = "#FF2500";
                        cell.style.color = "#0D19FF";
                        isConflict = true;
                    }
                    cell.style.borderTop = "1px solid green";
                }
                else {
                    //The first row is head data, so i-1 is the first task data 
                    var startDate = taskData.task[i-1]["startDate"];
                    var endDate = taskData.task[i-1]["endDate"];
                    if (startDate.toDateString() == headDates[j]) {
                        cell.innerText = taskData.task[i - 1]["taskName"];
                        taskTag = taskData.task[i - 1]["taskDateSpan"];
                        
                    }
                    if (taskTag > 0) {
                        cell.style.background = "#B393FF";
                        cell.style.borderBottom = "1px solid green";
                        cell.style.borderTop = "1px solid green";
                        taskTag--;
                    }
                }
                if (i == rowCount) {
                    //why not set this style in CSS file by table.borderBottom?
                    //since table.borderBottom doesn't work well if table row length is long.
                    cell.style.borderBottom = "1px solid green";
                }
            }
        }
        return isConflict;
    }

    function categoryTaskByDate(taskData) {
        var dateList = [];
        for (var i = 0; i < taskData.rows.length; i++) {
            dateList.push(new Date(taskData.rows[i][1]));
            dateList.push(new Date(taskData.rows[i][2]));
        }
        //Risk: may meet different date format for different regions
        dateList.sort(customSort());
        var dailyResource = new Array();
        var allTaskList = {
            task: [],
            dailyResource: dailyResource,
            dateMin: new Date(dateList[0]),
            dateMax: new Date(dateList[dateList.length - 1]),
            dateSpan: ((new Date(dateList[dateList.length - 1])) - (new Date(dateList[0]))) / (1000 * 60 * 60 * 24)
        };

        for (var j = 0; j < taskData.rows.length; j++){
            var item = taskData.rows[j];
            var startDate = new Date(item[1]);
            var endDate = new Date(item[2]);   

            allTaskList.task.push ({
                "taskName": item[0],
                //"taskType": item[1],
                "startDate": startDate,
                "endDate": endDate,
                "averageResource": item[3],
                "taskDateSpan": (endDate - startDate) / (1000 * 60 * 60 * 24) + 1
            });
            var dateIndex = startDate.toDateString();
            var taskDateSpan = (endDate - startDate) / (1000 * 60 * 60 * 24) + 1;
            dateIndex = new Date(dateIndex);
            while (endDate >= dateIndex) {
                if (!allTaskList.dailyResource[dateIndex.toDateString()]) {
                    allTaskList.dailyResource[dateIndex.toDateString()] = parseFloat(item[3]);
                }
                else {
                    allTaskList.dailyResource[dateIndex.toDateString()] += parseFloat(item[3]);
                }
                dateIndex.setDate(dateIndex.getDate() + 1);
            }
        }
        /*allTaskList.task.sort(function (element_a, element_b) {
            return element_a["taskType"] - element_b["taskType"] || (new Date(element_a["startDate"]).getTime()) - (new Date(element_b["startDate"]).getTime());
        });*/
        return allTaskList;
    }

    function customSort() {
        return function (o, p) {
            //var a, b;
            if (typeof o === "object" && typeof p === "object" && o && p) {
                //a = o[name];
                //b = p[name];
                if ((typeof o === typeof p) && o.getDate !="undifined") {
                    return o.getTime() < p.getTime() ? -1 : 1;
                }
                else {
                    return 0;
                }
            }
            else { throw ("error"); }
        }
    }

    function IsNumeric(input) {
        return (input - 0) == input && (input + '').replace(/^\s+|\s+$/g, "").length > 0;
    }

    function getData() {
        //Verify the valid input for the MAX resource
        var averageResourceNum = document.getElementById('message').value;
        if (!IsNumeric(averageResourceNum)) {
            document.getElementById('message').innerText = "Input a number please.";
            document.getElementById('message').style.color = "red";
            cleanTablerow("dataTable");
            document.getElementById('invalidTaskMessage').innerText = '';
            return;
        }
        
        Office.context.document.getSelectedDataAsync(Office.CoercionType.Table,
            { valueFormat: "formatted", filterType: "all" },
            function (asyncResult) {
                var error = asyncResult.error;
                if (asyncResult.status === Office.AsyncResultStatus.Failed) {
                    document.getElementById('invalidTaskMessage').style.display = 'block';
                    document.getElementById('invalidTaskMessage').innerText = 'Please select available rows, do not include any blank; go to www.dataexplorer.net if need details introduction';
                    document.getElementById('dataTable').style.display = 'none';
                    return;
                }
                else {
                    var message = '';
                    var invalidTaskDataMessageList = verifyTaskData(asyncResult.value).message;
                    if (invalidTaskDataMessageList.length > 0) {
                        for (var i = 0; i < invalidTaskDataMessageList.length; i++) {
                            message += "\n" + invalidTaskDataMessageList[i].msg;
                        }
                        document.getElementById('invalidTaskMessage').innerText = message;
                        document.getElementById('invalidTaskMessage').style.display = 'block';
                        document.getElementById('invalidTaskMessage').style.color = 'red';
                        document.getElementById('dataTable').style.display = 'none';
                    }
                    else {
                        var isConflict = createSimplyTable(asyncResult.value);
                        document.getElementById('dataTable').style.display = 'block';
                        document.getElementById('invalidTaskMessage').style.display = 'block';
                        if (isConflict) {
                            document.getElementById('invalidTaskMessage').innerText = 'Opps, conflict found, please notice red highlight date';
                            document.getElementById('invalidTaskMessage').style.color = 'red';
                        }
                        else {
                            document.getElementById('invalidTaskMessage').innerText = 'Cool, no resource conflicts found';
                            document.getElementById('invalidTaskMessage').style.color = 'green';
                        }
                    }
                }
            });
    }

    function verifyTaskData(taskData) {
        var messageList = {message: []};
        for (var i = 0; i < taskData.rows.length; i++) {
            if (!isValidDate(taskData.rows[i][1])) {
                messageList.message.push({
                    "row": i + 2,
                    "msg":'Invalid date format for start date in row ' + (i + 2)
                });
            }

            if (!isValidDate(taskData.rows[i][2])) {
                messageList.message.push({
                    "row": i + 2,
                    "msg": 'Invalid date format for end date in row ' + (i + 2)
                });
            }

            if (isValidDate(taskData.rows[i][1]) && isValidDate(taskData.rows[i][2])) {
                if ((new Date(taskData.rows[i][1])).getTime() > (new Date(taskData.rows[i][2])).getTime()) {
                    //Start date should be less than end date
                    messageList.message.push({
                        "row": i + 2,
                        "msg": 'Start date is late than end date in row ' + (i + 2)
                    });
                }
            }

            if (!parseFloat(taskData.rows[i][3])) {
                messageList.message.push({
                    "row": i + 2,
                    "msg": 'Input a valid number for average resource in row ' + (i + 2)
                });
            }
        }
        return messageList;
    }

    function isValidDate(date) {
        var matches = /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})$/.exec(date);
        if (!matches) return false;
        var composedDate = new Date(matches[3], (matches[1]- 1), matches[2]);

        return ((composedDate.getMonth() == (matches[1] - 1 )) &&
                (composedDate.getDate() == matches[2]) &&
                (composedDate.getFullYear() == matches[3]));
    }

    //return date offset than today, the date format is MM/DD/YYYY
    function customDate(offsetMonth, offsetDay, offsetYear) {
        var date = new Date();
        date.setDate(date.getDate() + offsetDay);
        date.setMonth(date.getMonth() + offsetMonth);
        date.setFullYear(date.getFullYear() + offsetYear);
        return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();;
    }

    function insertExampleData() {
        var myTable = new Office.TableData();
        myTable.headers = ["taskName", "startDate", "endDate", "averageResource"];
        myTable.rows = [
            ["This is task1", customDate(0, 0, 0), customDate(0, 6, 0), 4],
            ["This is task2", customDate(0, 1, 0), customDate(0, 5, 0), 3],
            ["This is task3", customDate(0, 2, 0), customDate(0, 11, 0), 5],
            ["This is task4", customDate(0, 3, 0), customDate(0, 8, 0), 3],
            ["This is task5", customDate(0, 4, 0), customDate(0, 11, 0), 3],
            ["This is task6", customDate(0, 3, 0), customDate(0, 9, 0), 3],
            ["This is task7", customDate(0, 2, 0), customDate(0, 12, 0), 5],
            ["This is task8", customDate(0, 1, 0), customDate(0, 10, 0), 3],
            ["This is task9", customDate(0, 0, 0), customDate(0, 6, 0), 4],
        ];
        Office.context.document.setSelectedDataAsync(myTable, function (asyncResult) {
            Office.context.document.bindings.addFromSelectionAsync(Office.BindingType.Table, { id: "myBinding" }, function (result) { });
        });
    }
    
})();